#include <algorithm>
#include <typeinfo>

#include "Stock.h"
#include "Product.h"
#include "HardDisk.h"
#include "Monitor.h"
#include "SDCard.h"
#include "Software.h"
#include "USB.h"

using std::sort;

Stock::Stock(vector < Product * > productList){
	this->productList = productList;
}

string Stock::productName[] = {"USB", "Hard disk", "Monitor", "SD card", "Application software"};

string Stock::productClassName[] = {"USB", "HardDisk", "Monitor", "SDCard", "Software"};

int Stock::getItemPrice(string id){
	setBufferItem(id);
	return bufferProductList[0]->getPrice();
}

int Stock::getItemStock(string id){
	setBufferItem(id);
	return bufferProductList[0]->getStock();
}

void Stock::addItem(string id, int quantity){
	setBufferItem(id);
	bufferProductList[0]->setStock(bufferProductList[0]->getStock() + quantity);
}

void Stock::reduceItem(string id, int quantity){
	addItem(id, 0 - quantity);
}

string Stock::getProductName(int index){
	return productName[index];
}

map <int, string> Stock::getItemsHeader(){
	if(bufferProductList[0]->getID() != "Simple" || bufferProductList[0]->getPrice() != 0)
		return bufferProductList[0]->getHeader();
	else{
		map <int, string> commonHeader;
		commonHeader[0] = "ID";
		commonHeader[1] = "Brand";
		commonHeader[2] = "Stock";
		commonHeader[3] = "Price";
		return commonHeader;
	}
}

map <int, int> Stock::getItemsHeaderLength(){
	return bufferProductList[0]->getHeaderLength();
}

map <int, string> Stock::getItemsDetails(){
	map <int, string> result;
	for(int i = 0; i < (int)bufferProductList.size(); i++){
		map <int, string> tempResult = bufferProductList[i]->getAllData(); //Get detail of a item
		int size = tempResult.size();

		//Append item to result map
		for(int j = 0; j < (int)tempResult.size(); j++)
			result[i*size + j] = tempResult[j];
	}
	return result;
}

int Stock::setBufferItem(string id){
	bufferProductList.clear();
	for(size_t i = 0; i < productList.size(); i++)
		//If found a hit
		if(productList[i]->getID() == id){
			bufferProductList.push_back(productList[i]); //Add to buffer
			for(int j = 0; j < 5; j++) //Found its product type
				if(typeid(*bufferProductList[0]).name() == "class " + productClassName[j])
					return j;
		}
	//Not found
	return -1;
}

int Stock::setBufferItem(int productType){
	bufferProductList.clear();
	if(productType == 5){
		bufferProductList.push_back(new Monitor("Simple", 0, "Simple", 0, 0));
	}
	for(size_t i = 0; i < productList.size(); i++)
		//If found a hit
		if(typeid(*productList[i]).name() == "class " + productClassName[productType]){
			bufferProductList.push_back(productList[i]); //Add to buffer
			return 1;
		}
	//Not found
	return -1;
}


int Stock::setBufferItem(int productType, int compareFactor){
	bufferProductList.clear();
	//search items by compare class type
	for(size_t i = 0; i < productList.size(); i++){
		if(typeid(*productList[i]).name() == "class " + productClassName[productType])
			bufferProductList.push_back(productList[i]); //Hit store into buffer
	}

	//Bubble sort
	for(int i = 0; i < ((int)bufferProductList.size() - 1); i++){
		for(int j = 0; j < ((int)bufferProductList.size() - (i + 1)); j++){
			if(bufferProductList[j]->isLarger(compareFactor, bufferProductList[j+1])){
				Product *temp = bufferProductList[j];
				bufferProductList[j] = bufferProductList[j+1];
				bufferProductList[j+1] = temp;
			}
		}
	}

	return bufferProductList.size();
}

int Stock::setBufferItem(int productType, int compareFactor, int threshold){
	setBufferItem(productType, compareFactor);

	//Start from the last item. If stock>threshold, remove from buffer
	for(int i = bufferProductList.size() - 1; i >= 0; i--){
		if(bufferProductList[i]->getStock() >= threshold)
			bufferProductList.erase(bufferProductList.begin() + i);
	}
	return bufferProductList.size();
}